package com.baidu.insertcode

import com.github.javaparser.StaticJavaParser
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration
import com.github.javaparser.ast.body.MethodDeclaration
import com.github.javaparser.ast.stmt.BlockStmt
import com.github.javaparser.ast.visitor.VoidVisitorAdapter
import com.github.javaparser.printer.PrettyPrinter
import java.io.File
import java.io.FileWriter


class InsertCode {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {

            val childUrls = listOf<String>(
                "app",
                "modules/base-module",
                "third-module"
            )

            childUrls.forEach { childUrl ->
                //当前项目
                //val file = File(System.getProperty("user.dir"))
                val file = File(System.getProperty("user.dir"), childUrl)
                System.out.println("main file ${file.absolutePath}")
                //模板代码文件
                val javaTemplateFile =
                    File(System.getProperty("user.dir"), "modules/base-module/insertCode/src/main/java/InsertCode.java")
                System.out.println("javaTemplateFile file ${javaTemplateFile.absolutePath}")

                val cu = StaticJavaParser.parse(javaTemplateFile)
                val methodList = mutableListOf<MethodDeclaration>()
                for (declaration in cu.childNodes) {
                    if (declaration is ClassOrInterfaceDeclaration) {
                        //将模板文件里的方法都保存起来
                        methodList.addAll(declaration.methods)
                    }
                }
                findJavaFile(file, methodList, javaTemplateFile)
            }
        }

        private fun findJavaFile(file: File,methodList :List<MethodDeclaration>,javaTemplateFile:File) {
            if (file.isDirectory) {
                file.listFiles().forEach {
                    findJavaFile(it,methodList,javaTemplateFile)
                }
            }//不处理build目录下的文件 和模板文件
            else if (javaTemplateFile != file &&!file.absolutePath.contains("build")) {
                val isJavaFile = file.name.endsWith(".java")
                if (isJavaFile) {
                    generateJavaFile(file,methodList)
                }
            }
        }

        private fun generateJavaFile(file: File,methodList :List<MethodDeclaration>) {
            val cu = StaticJavaParser.parse(file)
            val methodVisitor = MethodVisitor()
            methodVisitor.visit(cu, arrayOf(file,methodList))
            // 生成Java文件
            FileWriter(file).use { writer ->
                val printer = PrettyPrinter()
                val sourceCode: String = printer.print(cu)
                writer.write(sourceCode)
            }
            System.out.println("file ${file.name} 写完了")
        }
    }
}

class MethodVisitor : VoidVisitorAdapter<Any>() {
    override fun visit(md: MethodDeclaration, arg: Any) {
        super.visit(md, arg)
        try {
            val file=(arg as Array<Any>).get(0) as File
            val methodList=(arg as Array<Any>).get(1) as List<MethodDeclaration>
            //从模板文件里随机一个方法进行插入
            val methodDeclaration=methodList.random()
            val body1 = md.body.get()
            val body2 = BlockStmt()
            val firstLineCode = body1.statements.getOrNull(0)?.toString()
            //第一行代码 如果是 int password = 123456;就代表已经插入，则不进行修改
            if (firstLineCode != null && !firstLineCode.equals("int passwordfdare32432qresafdsagda32 = 123456;")) {
                body2.addStatement("int passwordfdare32432qresafdsagda32 = 123456;")
                methodDeclaration.body.get().statements.forEach {
                    body2.addStatement(it)
                }
            }
            body1.statements.forEach {
                body2.addStatement(it)

            }
            md.setBody(body2)
        } catch (e: Exception) {
            System.out.println(e.message)
        }
    }
}